using System;
using System.Drawing;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using System.Xml;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Highlighting.Xshd;

namespace Byond.Frontend.Controls
{
	/// <summary>
	/// Interaction logic for AvalonEditor.xaml
	/// </summary>
	public partial class AvalonEditor
	{
		#region static

		static AvalonEditor()
		{
			RegisterHighlightDefinition("XmlDoc2");
			RegisterHighlightDefinition("CSLight");
			RegisterHighlightDefinition("Xaml");

			//ICSharpCode.TextEditor.Document.HighlightingManager.Manager.AddSyntaxModeFileProvider(
			//    new SyntaxModeProvider());
		}

		private static void RegisterHighlightDefinition(string docName)
		{
			HighlightingManager.Instance.RegisterHighlighting(
				docName,
				new string[0],
				() =>
				{
					var type = typeof(AvalonEditor);
					using (var stream = type.Assembly.GetManifestResourceStream(type.Namespace + "." + docName + ".xshd"))
					{
						var reader = XmlReader.Create(stream);
						return HighlightingLoader.Load(reader, HighlightingManager.Instance);
					}
				});
		}

		#endregion

		public AvalonEditor()
		{
			InitializeComponent();

			textEditor.TextArea.LeftMargins
				.OfType<LineNumberMargin>()
				.ForEach(it => it.Margin = new Thickness(0, 0, 10, 0));
			textEditor.TextArea.TextView.Margin = new Thickness(10, 0, 0, 0);
		}

		public EditorLanguage EditorLanguage
		{
			set
			{
				var highlightingDefinition = value == EditorLanguage.CSharp
					? HighlightingManager.Instance.GetDefinition("CSLight")
					: HighlightingManager.Instance.GetDefinition("Xaml");

				if (highlightingDefinition == null)
					throw new Exception("Could not find highlighter definition for: " + value);

				textEditor.SyntaxHighlighting = highlightingDefinition;
			}
		}

		#region Text DP

		public string Text
		{
			get { return (string)GetValue(TextProperty); }
			set { SetValue(TextProperty, value); }
		}

		// Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty TextProperty =
			DependencyProperty.Register(
				"Text",
				typeof(string),
				typeof(AvalonEditor),
				new UIPropertyMetadata(null, (s, e) =>
					{
						// HACK: Beim 1. Mal soll der Text an den Editor weitergegeben werden
						var editor = (AvalonEditor)s;

						// TODO: Geht nur, wenn im Viewmodel das Prop einmal gesetzt wurde und auch OnPropChg aufgerufen wurde
						if (e.OldValue != null)
							return;

						editor.textEditor.Text = e.NewValue.ToString();
						editor.textEditor.TextChanged += editor.textEditor_TextChanged;
					}));

		#endregion

		public void SetFocusOnCarret()
		{
			textEditor.Focus();
		}

		private void textEditor_TextChanged(object sender, EventArgs e)
		{
			Text = textEditor.Text;
		}
	}
}
